/**
 * 表达式求值
 * 
 * 题目：输入一串string类型的表达式（如3*4+5），计算结果
 * 注意：需要找到优先级最高的字符（* / 大于 + -），最后再考虑括号()
 * 
 * 思路：
 */

const maxVal = 999999;

let level = 0;

/**
 * @description
 * @author luyaxiang
 * @date 2021/07/23
 * @param {*} str 输入的表达式字符串（如：3+4*5）
 * @param {*} l 当前处理表达式的左边界
 * @param {*} r 右边界 再left和right范围内遍历
 */
function calc(str, l, r) {
  let pos = -1; // 循环结束后，pos指向left到right中【优先级最高】的字符(+-*/)
  let pri = maxVal - 1; // 上一次的优先级，默认给一个很多大的数
  let temp = 0; // temp是权重
  for (let i = l; i< r; i++) {
    let cur = maxVal; // 这里cur初始值（maxVal）是比pri（初始值是maxVal - 1）大的
    switch(str[i]) {
      case "(": temp += 1000; break; // 只修改了优先级基数
      case ")": temp -= 1000; break;
      case "+":
      case "-": cur = temp + 1; break;
      case "*":
      case "/": cur = temp + 2; break;
    }
    // console.info("cur:", cur, ";pri:", pri, ";i:", i, ";value:", str[i])
    /**
     * 从结果上看，这里保存的是操作符优先级低的 + -；为啥？？？
     * 
     * 这里我理解的思路是：
     * 拿 3*4+5来举例，这里期望的是先计算 3*4（存储为A）然后计算A + 5；所以 + 这个操作符在栈底，3*4在栈头。
     * 优先级低的更应该先被记录
     *  */
    if (cur <= pri) { // 如果比上一次的小。
      pos = i; // 当前操作符的下标
      pri = cur; // 保存当前操作符的优先级，遇到 + - 是1；* / 是2
    }
  }
  if (pos === -1) { // 这里表示没有运算符，比如3
    return Number(str.slice(l , r + 1).replace("(", "").replace(")", "")); // 好好学习正则！！！！！
  }
  let a = calc(str, l, pos - 1);
  let b = calc(str, pos + 1, r);
  

  switch(str[pos]) {
    case "+": return a + b;
    case "-": return a - b;
    case "*": return a * b;
    case "/": return a / b;
  }
}

function main(str) {
  console.info(calc(str, 0, str.length))
}

// main("3*4+5")
// main("1+1+1")
// main("3+4*5")
// main("3+4*5*2")
main("3*(1+2)")